#pragma once

#include <sys/epoll.h>
#include "Log.h"
#include "Common.h"

namespace zmh
{
    // 对多路转接技术的封装
    class Epoll
    {
        void Helper(int fd, int op, epoll_event *events)
        {
            if (epoll_ctl(_eplfd, op, fd, events) < 0)
                LOG(LogLevel::ERROR) << "epoll_ctl error: " << strerror(errno);
        }

    public:
        Epoll()
        {
            _eplfd = epoll_create(1); // 参数虽然无实际意义，但仍必须＞零
            if (_eplfd < 0)
            {
                LOG(LogLevel::FATAL) << "epoll_create error: " << strerror(errno);
                exit(-1);
            }
            LOG(LogLevel::INFO) << "epoll_create success: " << _eplfd;
        }
        void AddEvent(int fd, uint32_t events)
        {
            struct epoll_event event;
            event.events = events;
            event.data.fd = fd;

            Helper(fd, EPOLL_CTL_ADD, &event);
        }
        void DelEvent(int fd)
        {
            Helper(fd, EPOLL_CTL_DEL, nullptr);
        }
        void ModEvent(int fd, uint32_t events)
        {
            struct epoll_event event;
            event.events = events;
            event.data.fd = fd;

            Helper(fd, EPOLL_CTL_MOD, &event);
        }
        int Wait(struct epoll_event *events, int maxevents, int timeout_ms = -1)
        {
            int n = epoll_wait(_eplfd, events, maxevents, timeout_ms);
            if (n < 0 && errno != EINTR)
                LOG(LogLevel::ERROR) << "epoll_wait error: " << strerror(errno);
            else
                LOG(LogLevel::INFO) << "epoll_wait success";
            return n;
        }
        ~Epoll()
        {
            if (_eplfd >= 0)
                close(_eplfd);
        }

    private:
        int _eplfd; // 指向epoll的文件描述符
    };
}